﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;


namespace SocketClient
{
    class Http
    {
        public static HttpCli CreateHttpClient()
        {
            return new HttpCli();
        }
        public static HttpCli CreateHttpClient(string url)
        {
            return new HttpCli(url);
        }
        public static HttpCli CreateHttpClient(string tenant, string token)
        {
            return new HttpCli(tenant, token);
        }
        public static HttpCli CreateHttpClient(string url, string tenant, string token)
        {
            return new HttpCli(url, tenant, token);
        }
        public class HttpCli
        {
            private String _tenant = "1";
            private String _token = null;
            private Uri uri_ = null;
            private string contentType_ = "application/json";

            public HttpCli(string url)
            {
                if (url == null || url.Length <= 0)
                {
                    throw new ArgumentNullException("url 不能为空！");
                }
                uri_ = new Uri(url);
            }
            public HttpCli()
            {

            }
            public HttpCli(string tenant, string token)
            {
                _tenant = tenant;
                _token = token;
            }
            public HttpCli(string url, string tenant, string token)
            {
                _tenant = tenant;
                _token = token;
                if (url == null || url.Length <= 0)
                {
                    throw new ArgumentNullException("url 不能为空！");
                }
                uri_ = new Uri(url);
            }
            private void useHttps()
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
                ServicePointManager.ServerCertificateValidationCallback =
                    new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, errors) =>
                    {
                        //https 总是接收
                        return true;
                    });
            }
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            public HttpCli Url(string url)
            {
                if (url == null || url.Length <= 0)
                {
                    throw new ArgumentNullException("url 不能为空！");
                }
                uri_ = new Uri(url);
                return this;
            }
            /// <summary>
            /// 设置ContentType
            /// </summary>
            /// <param name="contentType">默认为  application/json</param>
            /// <returns></returns>
            public HttpCli ContentType(string contentType = "application/json")
            {
                contentType_ = contentType;
                return this;
            }
            /// <summary>
            /// Get请求
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            public HttpResp Get(string url)
            {
                if (url.StartsWith("https"))
                {
                    useHttps();
                }
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
                HttpResp hr = SendAsync(request).Result;
                return hr;
            }
            /// <summary>
            /// 异步Get
            /// </summary>
            /// <param name="url"></param>
            /// <param name="callback"></param>
            public async void GetAsync(string url, Action<HttpResp> callback)
            {
                if (url.StartsWith("https"))
                {
                    useHttps();
                }
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
                request.Headers.Add("X-Saas-Tenant", _tenant);
                request.Headers.Add("X-Access-Token", _token);
                HttpResp hr = await SendAsync(request);
                if (callback != null)
                {
                    callback.Invoke(hr);
                }
            }
            /// <summary>
            /// Post
            /// </summary>
            /// <param name="postData"></param>
            /// <returns></returns>
            public HttpResp Post(string postData)
            {
                if (uri_ == null)
                {
                    throw new ArgumentNullException("请先设置url！");
                }
                if (uri_.OriginalString.StartsWith("https"))
                {
                    useHttps();
                }
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri_);
                request.Content = new StringContent(postData, Encoding.UTF8, contentType_);
                HttpResp hr = SendAsync(request).Result;
                return hr;
            }
            /// <summary>
            /// 异步Post
            /// </summary>
            /// <param name="postData"></param>
            /// <param name="callback"></param>
            public async void PostAsync(string postData, Action<HttpResp> callback)
            {
                if (uri_ == null)
                {
                    throw new ArgumentNullException("请先设置url！");
                }
                if (uri_.OriginalString.StartsWith("https"))
                {
                    useHttps();
                }
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri_);
                request.Headers.Add("X-Saas-Tenant", _tenant);
                request.Headers.Add("X-Access-Token", _token);
                request.Content = new StringContent(postData, Encoding.UTF8, contentType_);
                HttpResp hr = await SendAsync(request);
                if (callback != null)
                {
                    callback.Invoke(hr);
                }
            }
            /// <summary>
            /// 异步Post
            /// </summary>
            /// <param name="postData"></param>
            /// <param name="callback"></param>
            public async void PostAsync(string url, string postData, Action<HttpResp> callback)
            {
                if (url == null)
                {
                    throw new ArgumentNullException("请先设置url！");
                }
                if (url.StartsWith("https"))
                {
                    useHttps();
                }
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri_);
                request.Headers.Add("X-Saas-Tenant", _tenant);
                request.Headers.Add("X-Access-Token", _token);
                request.Content = new StringContent(postData, Encoding.UTF8, contentType_);
                HttpResp hr = await SendAsync(request);
                if (callback != null)
                {
                    callback.Invoke(hr);
                }
            }

            public async void UploadFileAsync(string filePath, Action<HttpResp> callback)
            {
                HttpResp hr = null;
                if (uri_ == null)
                {
                    throw new ArgumentNullException("请先设置url！");
                }
                if (uri_.OriginalString.StartsWith("https"))
                {
                    useHttps();
                }
                //String OutPath = GValues.pdfPath + "\\selectDWGWindow.pdf";
                //for (int i = 0; i < 3; i++)
                //{
                //    // 判断文件是否存在
                //    if (!File.Exists(filePath))
                //    {
                //        Task.Delay(TimeSpan.FromSeconds(2)).Wait();
                //    }
                //}

                try
                {
                    using (var content = new MultipartFormDataContent())
                    {
                        // 添加文件内容
                        using (var fileStream = new FileStream(filePath, FileMode.Open))
                        {
                            var streamContent = new StreamContent(fileStream);
                            var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync());
                            fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data");
                            content.Add(fileContent, "file", Path.GetFileName(filePath));

                            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri_);
                            request.Headers.Add("X-Saas-Tenant", _tenant);
                            request.Headers.Add("X-Access-Token", _token);
                            request.Headers.Add("biz", "drawing/" + GValues.tenant);
                            request.Content = content;
                            // 创建请求
                            // 发送请求
                            hr = await SendAsync(request);
                            //response.EnsureSuccessStatusCode();

                        }
                    }
                    if (callback != null)
                    {
                        try
                        {
                            if (hr != null)
                            {
                                //Task.Delay(TimeSpan.FromSeconds(2)).Wait();
                                callback.Invoke(hr);
                            }
                        }
                        catch (System.Exception e)
                        {
                            // LogHelper.WriteLog("Http 回调报错！" + e.Message + " hr: " + JsonConvert.SerializeObject(hr));
                            throw new ArgumentNullException("Http 回调报错！");
                        }
                    }
                }
                catch (Exception e)
                {
                    GValues.uploadComplete = true;
                    LogHelper.WriteLog("读取文件报错！", null);
                }
            }

            private Task<HttpResp> SendAsync(HttpRequestMessage request)
            {
                return Task.Run(() =>
                {
                    HttpResponseMessage response = null;
                    HttpResp httpResp = null;
                    Dictionary<string, string> headers = null;
                    using (HttpClient client = new HttpClient(
                        new HttpClientHandler
                        {
                            AutomaticDecompression = DecompressionMethods.GZip
                        | DecompressionMethods.Deflate
                        }))
                    {
                        //异步发送并等待结果
                        try
                        {
                            client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("GZIP"));
                            response = client.SendAsync(request).Result;
                            HttpStatusCode httpCode = response.StatusCode;
                            headers = response.Headers.ToDictionary(kv => kv.Key, kv => Convert.ToString(kv.Value.ToArray()));
                            if (response.IsSuccessStatusCode)
                            {
                                byte[] bs = response.Content.ReadAsByteArrayAsync().Result;
                                httpResp = new HttpResp(httpCode, headers, bs, response.StatusCode.ToString());
                            }
                            else
                            {
                                httpResp = new HttpResp(httpCode, headers, null, response.ReasonPhrase);
                            }
                        }
                        catch (Exception ex)
                        {
                            httpResp = new HttpResp(HttpStatusCode.BadRequest, null, null, ex.Message);
                        }
                    }
                    return httpResp;
                });
            }
        }
        public class HttpResp
        {
            private HttpStatusCode _code;
            private Dictionary<string, string> _Headers;
            public string _Error;
            public byte[] _AckBytes;

            public HttpStatusCode Code
            {
                get { return _code; }
                set
                {
                    // 在 set 方法中添加额外逻辑
                    // 例如，可以在这里验证设置的值
                    _code = value;
                }
            }

            public Dictionary<string, string> Headers
            {
                get { return _Headers; }
                set
                {
                    _Headers = value;
                }
            }
            public string Error
            {
                get { return _Error; }
                set { _Error = value; }
            }
            public byte[] AckBytes
            {
                get { return _AckBytes; }
                set { _AckBytes = value; }
            }
            /// <summary>
            /// Get AckStr
            /// </summary>
            /// <param name="encode"></param>
            /// <returns></returns>
            public string AckStr(Encoding encode)
            {
                return AckBytes == null ? string.Empty : encode.GetString(AckBytes);
            }
            /// <summary>
            ///Get AckStr with default UTF-8
            /// </summary>
            /// <returns></returns>
            public string AckStr()
            {
                return AckStr(Encoding.UTF8);
            }
            public HttpResp(HttpStatusCode code, Dictionary<string, string> headers, byte[] ack, string error)
            {
                Code = code;
                AckBytes = ack;
                Headers = headers;
                Error = error;
            }
        }
    }
}
